from neo4j import GraphDatabase


class Neo4jConnection:
    def __init__(self):
        self.uri = "neo4j://localhost:7687"
        self.username = "neo4j"
        self.password = "JGL12345"
        self.driver = GraphDatabase.driver(self.uri, auth=(self.username, self.password))

    def __execute_query(self, query, params):
        with self.driver.session() as session:
            result = session.run(query, params)
            return [record for record in result]

    def query_person(self, person_name):
        query = "match (p:Person {name: $name}) return p"
        return self.__execute_query(query, {"name": person_name})

    def query_person_relation(self, person_name):
        query = ("match (pa:Person)-[r:relation]->(pb:Person) "
                 "where pa.name=$name "
                 "return pb.name as name, r.type as type")
        return self.__execute_query(query, {"name": person_name})

    def query_person_alias(self, person_name):
        query = "match (p:Person {name: $name}) return p.alias as alias"
        return self.__execute_query(query, {"name": person_name})

    def query_person_participate_event(self, person_name):
        query = ("match (p:Person)-[r:participate_event]->(e:Event) "
                 "where p.name=$name "
                 "return e.name as event")
        return self.__execute_query(query, {"name": person_name})

    def query_place(self, place_name):
        query = "match (p:Place {name: $name}) return p"
        return self.__execute_query(query, {"name": place_name})

    def query_event_on_place(self, place_name):
        query = ("match (p:Place)-[r:event_occurred]->(e:Event) "
                 "where p.name=$name "
                 "return e.name as event")
        return self.__execute_query(query, {"name": place_name})

    def query_house(self, house_name):
        query = "match (h:House {name: $name}) return h"
        return self.__execute_query(query, {"name": house_name})

    def query_house_persons(self, house_name):
        query = ("match (h:House)-[r:owned_person]->(p:Person) "
                 "where h.name = $name "
                 "return p.name as name")
        return self.__execute_query(query, {"name": house_name})

    def query_event(self, event_desc):
        query = "match (e:Event {name: $name}) return e"
        return self.__execute_query(query, {"name": event_desc})

    def query_event_participate(self, event_desc):
        query = ("match (e:Event)-[r:related_person]->(p:Person) "
                 "where e.name=$name "
                 "return p.name as name")
        return self.__execute_query(query, {"name": event_desc})

    def query_event_time_or_place(self, event_desc):
        query = ("match (e:Event {name: $name}) "
                 "optional match (e)-[:occurred_on]->(p:Place) "
                 "return e.name as name, p.name as location, e.time as time")
        return self.__execute_query(query, {"name": event_desc})
    
    def query_specific_relation(self, person_name, relation_name):
        query = ("match (p1:Person {name: $name})-[r:relation {type: $type}]-(p2:Person)"
                 "return p2")
        return self.__execute_query(query, {"name": person_name, "type": relation_name})


graph = Neo4jConnection()
